﻿using Guitar.Comet.Message;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using XL.Framework.Domain.Core.Repository;

namespace Guitar.Comet.Client
{
    /// <summary>
    /// 消息总线（实现消息的发送机制）
    /// </summary>
    public class MessageBus : IMessageBus
    {

        private readonly ICommandRepository<MessageEnvelope> _messageRepsoitory;
        private readonly IMessageDistribution _messageDistribution;
        private static readonly object LockObject = new object();
        private static int _retrySendMessageCount = 0, _failSendMessageCount = 0;
        private const int MaxRrySendMessageCount = 3;


        public MessageBus(ICommandRepository<MessageEnvelope> messageRepsoitory, IMessageDistribution messageDistribution)
        {
            _messageRepsoitory = messageRepsoitory;
            _messageDistribution = messageDistribution;
            _messageDistribution.FailActionEvent += _messageDistribution_FailAction;
            _messageDistribution.SuccessActionEvent += _messageDistribution_SuccessAction;
        }

        /// <summary>
        /// 成功发送消息事件处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _messageDistribution_SuccessAction(object sender, CometEventArgs e)
        {
            _retrySendMessageCount = MaxRrySendMessageCount;
            Console.Write(e.Message);
            Console.Write(Environment.NewLine);

        }

        private void _messageDistribution_FailAction(object sender, CometEventArgs e)
        {
            _retrySendMessageCount++;
            _failSendMessageCount++;

            Console.Write(e.Message);
            Console.Write(Environment.NewLine);
        }


        /// <summary>
        /// 单线程处理消息
        /// </summary>
        /// <param name="message"></param>
        public void Handle(MessageEnvelope message)
        {
            lock (LockObject)
            {
                _messageRepsoitory.Add(message);

                while (_retrySendMessageCount < MaxRrySendMessageCount) // 重试次数不宜太多,因为会阻塞其它消息的发送
                {
                    _messageDistribution.SendMessage(message);
                }
                if (_failSendMessageCount == MaxRrySendMessageCount) // if retry over maxtrycount store fail message 
                {
                    message.Status = 1;
                    _messageRepsoitory.Add(message);
                }

                _retrySendMessageCount = 0;
                _failSendMessageCount = 0;
            }
        }
    }
}
